#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
#include <string.h>
//#include <mpi.h>
#include <fftw3-mpi.h>
#include <time.h>

#define COMM MPI_COMM_WORLD
#define PI 2*acos(0)
#define INT    MPI_INTEGER
#define FMODE  FFTW_PATIENT


typedef struct ctrl_param
{
  char		runname[80], rname[80];
  double	cfl, l, b, a;
  double	tmax, tio, offset, delta2;
  int		m_order, gFlag, mFlag;
  ptrdiff_t	n, heat, rs_flag;
  double	Npart;			// target number of particles for heat equation
  double	m;			// regularization of potential
} ctrl_str, *ctrl_ptr;

typedef struct work_array
{
  fftw_complex  *wrk, *ft, *grv, *tmp, *grv2;
  ptrdiff_t    	l_n0, l_0_start, alloc_local;
} work_str, *work_ptr;

typedef struct times
{
  double      dt;
  double      ph_time, io_time;
  double      my_fft_time;

} time_str, *time_ptr;

/* arrays.c  */

extern void arr3d_init(ctrl_ptr in, work_ptr wrk);

/* init.c    */

extern void load_params(int *argc, char ***argv, ctrl_ptr in);
extern void write_log(ctrl_ptr in);

/*  ic_s.c   */

extern void init_ic(ctrl_ptr ctrl);
extern void set_ic(ctrl_ptr ctrl, work_ptr in);
extern fftw_complex step(ctrl_ptr ctrl);
extern fftw_complex step(ctrl_ptr ctrl);


/*  ffts.c   */

extern void lin_step(work_ptr in, fftw_complex step);
extern void nnl_step(work_ptr in, fftw_complex step);
extern void init_ffts(ctrl_ptr ptr, work_ptr work);
extern void my_fft_bench(work_ptr work);
extern void fft_laplace(work_ptr in);
extern void convolution(work_ptr in);
extern void ft_potential();
extern double particles(work_ptr in);


/*   io.c    */

extern void init_io(ctrl_ptr ctrl);
extern void save_data(work_ptr in, char *outfile);
extern void load_data(work_ptr in, char *infile );
extern void save_text(work_ptr in, char* infile);
extern void save_data2(work_ptr in, char* outfile,fftw_complex* ptr);

/*  timers.c  */

extern double adv_time();
extern void measure_fft(work_ptr wrk, int num);
extern int time_out(work_ptr work, ctrl_ptr ctrl);
extern void save_temporal(work_ptr work, char* infile);

/*  split_step.c  */

extern void init_splitstep();
extern void s_order(ctrl_ptr ctrl, work_ptr in);
